package cn.sharp.bbs.common;


import cn.sharp.bbs.entity.BO.CurrentUser;
import cn.sharp.bbs.service.CommonService;
import cn.sharp.bbs.service.LoginService;
import cn.sharp.bbs.service.SecurityService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;

/**
 * 自定义的权限拦截器, 对请求进行权限的拦截, 同时生成CurrentUser注入RequestAttribute
 */
public class PermissionInterceptor implements HandlerInterceptor {

    private static final Logger log = LoggerFactory.getLogger(PermissionInterceptor.class);
    private static final String[] PublicPath = {
            "/error", "/register", "/login"
    };

    private final LoginService loginService = CommonConfig.getApplicationContext()
            .getBean(LoginService.class);

    private final CommonService commonService = CommonConfig.getApplicationContext()
            .getBean(CommonService.class);

    private final SecurityService securityService = CommonConfig.getApplicationContext()
            .getBean(SecurityService.class);

    /**
     * 在请求处理前进行拦截和权限验证
     * TODO: 根据RBAC进行拦截处理
     * @param request 请求体
     * @param response 响应
     * @param handler 处理
     * @return 是否放行
     * @throws Exception 抛出异常
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestPath = request.getServletPath();
        String token = request.getHeader(Constants.HEADER_TOKEN);
        CurrentUser user = null;
        if(token!=null){
            try {
                log.debug("Try to parse CurrentUser");
                TokenUtils.verifyToken(token, loginService);
                user = TokenUtils.getUserInfo(token, commonService);
                log.debug("Attached " + user + " to RequestAttribute");
            }catch (Exception ignored){ }
        }
        request.setAttribute("CurrentUser", user);
        if(!isPublicPath(requestPath)){
            log.info("Accessing non-public path: " + requestPath);
            if(user==null){
                Utils.outJson(response, Result.fail(Result.ERR_CODE_UNLOGIN,  "未登陆或口令未指定"));
                return false;
            }

            log.debug("Able to access: " + securityService.isUserAbleToAccessApi(user.getU_id(), requestPath));
            if(!securityService.isUserAbleToAccessApi(user.getU_id(), requestPath)){
                Utils.outJson(response, Result.fail(Result.ERROR_CODE_PERM,  "权限不足"));
                return false;
            }
        }
        return true;
    }

    //TODO: 划定公开路径

    /**
     * 检查访问的路径是否为公开的
     * @param requestPath 访问的路径
     * @return 是否公开
     */
    private boolean isPublicPath(String requestPath) {
//        return Arrays.asList(PublicPath).contains(requestPath);
        return true;
    }
}
